package com.atmilan.quartz.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.atmilan.quartz.utils.product.XyyProductUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.atmilan.quartz.constant.Constants;
import com.atmilan.quartz.constant.enums.ProductTypeEnum;
import com.atmilan.quartz.constant.enums.SyncStatusEnum;
import com.atmilan.quartz.model.dto.crmeb.StoreProductCrmebRequest;
import com.atmilan.quartz.model.dto.xyy.XyyProductResDTO;
import com.atmilan.quartz.model.dto.xyy.XyyProductResDTO.XyyGoodsRes;
import com.atmilan.quartz.model.dto.xyy.XyyProductSkuResDTO;
import com.atmilan.quartz.model.dto.xyy.XyyProductSkuResDTO.TStorhouse;
import com.atmilan.quartz.model.entity.crmeb.StoreProduct;
import com.atmilan.quartz.model.entity.crmeb.SystemConfig;
import com.atmilan.quartz.model.entity.xyy.XyyProduct;
import com.atmilan.quartz.model.entity.xyy.XyyProductSku;
import com.atmilan.quartz.service.IStoreProductAttrService;
import com.atmilan.quartz.service.IStoreProductAttrValueService;
import com.atmilan.quartz.service.IStoreProductService;
import com.atmilan.quartz.service.ISystemConfigService;
import com.atmilan.quartz.service.IXyyProductService;
import com.atmilan.quartz.service.IXyyProductSkuService;
import com.atmilan.quartz.service.IXyySyncService;
import com.atmilan.quartz.utils.RedisUtil;
import com.atmilan.quartz.utils.source.SourceXyyProductUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import lombok.extern.slf4j.Slf4j;

/**
 * @author Howe Hsiang
 */
@Slf4j
@Service
public class XyySyncServiceImpl implements IXyySyncService {

    @Autowired
    RedisUtil redisUtil;
    @Autowired
    ISystemConfigService systemConfigService;
    @Autowired
    IXyyProductService xyyProductService;
    @Autowired
    IXyyProductSkuService xyyProductSkuService;
    @Autowired
    IStoreProductService storeProductService;
    @Autowired
    IStoreProductAttrService storeProductAttrService;
    @Autowired
    IStoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    SourceXyyProductUtil sourceXyyProductUtil;
    @Autowired
    XyyProductUtil xyyProductUtil;
    
    /**
     * 获取远程数据并保存到数据源
     */
    @Override
    public Boolean syncXyyProduct() {
        // 数据清空
        xyyProductService.deleteAll();
        xyyProductSkuService.deleteAll();

        int pageNo = 1;
        int pageSize = 100;
        int pageCount = 1;
        long millis = System.currentTimeMillis();
        String token = xyyProductUtil.getXyyToken(millis);
        while(pageNo <= pageCount) {
            try {
                XyyProductResDTO xyyProductResDTO = xyyProductUtil.selectXyyPage(pageNo, pageSize, millis, token);
                if(null == xyyProductResDTO) {
                    log.info("--------------- xyy获取商品接口请求失败 ---------------");
                    continue;
                }
                
                List<XyyGoodsRes> xyyGoodsRess = xyyProductResDTO.getGoods();
                
                // 过滤所有可售商品数据, 查询对应sku
                List<XyyGoodsRes> availableXyyGoodsRess = new ArrayList<XyyGoodsRes>();
                List<XyyProductSkuResDTO> xyyProductSkuResDTOs = new ArrayList<XyyProductSkuResDTO>();
                for(XyyGoodsRes xyyGoodsRes : xyyGoodsRess) {
                    if(1== xyyGoodsRes.getIsOnSale() && 0 == xyyGoodsRes.getIsDeleted()) {
                        availableXyyGoodsRess.add(xyyGoodsRes);
                        int goodsId = xyyGoodsRes.getGoodsId();
                        List<XyyProductSkuResDTO> skus = xyyProductUtil.getXyySkus(goodsId, millis, token);
                        xyyProductSkuResDTOs.addAll(skus);
                    }
                }
                // 商品保存
                saveGoods(availableXyyGoodsRess, xyyProductSkuResDTOs);
                
                // 计算页数
                pageCount = (xyyProductResDTO.getCount() + pageSize - 1) / pageSize;
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("--------------- 喜洋洋远程抓取数据, 第: {} 页,  总共: {} 页, 总耗时: {} 分  ---------------", pageNo, pageCount, (int)((System.currentTimeMillis() - millis) / 1000 / 60));
            pageNo++;
        }
    
        return true;
    }
    
    // 商品源数据保存
    private void saveGoods(List<XyyGoodsRes> availableXyyGoodsRess, List<XyyProductSkuResDTO> xyyProductSkuResDTOs) {
        // 拆分商品sku不同仓储位置
        List<XyyProductSku> xyyProductSkuEntity = new ArrayList<>();
        for(XyyProductSkuResDTO xyySkuResult : xyyProductSkuResDTOs) {
            // 没库存或未上架
            if(0 >= xyySkuResult.getStock() || 1 != xyySkuResult.getIsOnSale()) {
                continue;
            }
            
            List<TStorhouse> tStorhouses = xyySkuResult.getTStorhouses();
            for(TStorhouse tStorhouse : tStorhouses) {
                // 没现货
                if(0 >= tStorhouse.getXianhuoStock()) {
                    continue;
                }
                // 组装新的sku
                XyyProductSku xyyProductSku = new XyyProductSku();
                BeanUtils.copyProperties(xyySkuResult, xyyProductSku);
                xyyProductSku.setSpecId(xyyProductSku.getSpecId() + "-" + tStorhouse.getShId());
                xyyProductSku.setShId(tStorhouse.getShId());
                xyyProductSku.setShName(tStorhouse.getShName());
                xyyProductSku.setStock(tStorhouse.getStock());
                xyyProductSku.setQihuoStock(tStorhouse.getQihuoStock());
                xyyProductSku.setXianhuoStock(tStorhouse.getXianhuoStock());
                
                xyyProductSkuEntity.add(xyyProductSku);
            }
        }
        
        // 商品数据
        List<XyyProduct> xyyProductEntity = new ArrayList<>();
        for(XyyGoodsRes xyyProduct : availableXyyGoodsRess) {
            Integer goodsId = xyyProduct.getGoodsId();
            String redisKey = "job:sync:xyy:" + goodsId;
            if (null != redisUtil.get(redisKey)) {
                log.info("--------------- 该商品: {}, 已保存, 不进行处理  ---------------", goodsId);
                continue;
            } else {
                redisUtil.set(redisKey, goodsId, 3L, TimeUnit.MINUTES);
            }
            XyyProduct productEntity = new XyyProduct();
            BeanUtils.copyProperties(xyyProduct, productEntity);
            productEntity.setDetailImage(JSONArray.toJSONString(xyyProduct.getDetailImage()));
            xyyProductEntity.add(productEntity);
        }
        
        xyyProductService.saveBatch(xyyProductEntity);
        xyyProductSkuService.saveBatch(xyyProductSkuEntity);
    }

    @Override
    public Boolean pushXyyProduct() {
        try {
            // 当次更新少于1千条, 则不更新, 并且重新拉取
            int count = xyyProductService.count();
            if(1000 > count) {
                systemConfigService.update(Wrappers.<SystemConfig>lambdaUpdate()
                        .eq(SystemConfig :: getName, Constants.XYY_SYNC_STATUS)
                        .set(SystemConfig :: getFormId, SyncStatusEnum.PUSH)
                        .set(SystemConfig :: getUpdateTime, new Date())
                        );
                log.info("--------------- 喜洋洋商品源数据, 少于规定条数, 不进行下发, 总条数为: {} ---------------", count);
                return false;
            }
            
            // 将所有喜洋洋商品更新状态置为未更新
            storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
                    .eq(StoreProduct :: getIsEurope, ProductTypeEnum.XYY.getCode())
                    .set(StoreProduct :: getUpdateFlag, false)
                    );
            
            // 商品更新操作
            int pageNo = 1;
            int pageSize = 100;
            int maxPage = (count + pageSize - 1) / pageSize;
            log.info("--------------- 开始分页查询喜洋洋商品源数据, 本次更新总条数为: {} ---------------", count);

            long millis = System.currentTimeMillis();
            while (pageNo <= maxPage) {
                try {
                    PageHelper.startPage(pageNo, pageSize);
                    List<XyyProduct> xyyProducts = xyyProductService.list();
                    PageInfo<XyyProduct> pageInfo = PageInfo.of(xyyProducts);
                    List<XyyProduct> products = pageInfo.getList();
                    buildProduct(products);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                log.info("--------------- 喜洋洋下发商品到数据库, 当前页数: {}, 总页数: {}, 耗时: {} 分 ---------------", pageNo, maxPage, (int)((System.currentTimeMillis() - millis) / 1000 / 60));
                pageNo++;
            }
            // 图搜删除
            storeProductService.delSeachImage(ProductTypeEnum.XYY);
            // 下架所有未更新数据
            storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
                    .eq(StoreProduct::getIsEurope, ProductTypeEnum.XYY.getCode())
                    .eq(StoreProduct::getUpdateFlag, false)
                    .eq(StoreProduct :: getIsShow, true)
                    .eq(StoreProduct :: getIsDel, false)
                    .set(StoreProduct::getIsShow, false)
                    .set(StoreProduct::getStock, 0)
                    .set(StoreProduct::getLastPushTime, new Date())
                    .set(StoreProduct::getIsTusou, false)
                    );
            // 下架所有sku库存
            storeProductService.downloadSku(ProductTypeEnum.XYY.getCode());

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return false;
    }

    /**
     * 商品构建处理
     * @Description:  
     * @author daigb 
     * @param @param products
     * @return void
     * @throws
     */
    private void buildProduct(List<XyyProduct> products) {
        try {
            for (XyyProduct product : products) {
                List<XyyProductSku> skus = xyyProductSkuService.list(Wrappers.<XyyProductSku>lambdaQuery()
                        .eq(XyyProductSku :: getGoodsId, product.getGoodsId())
                        .eq(XyyProductSku :: getShId, "2")
                        .isNotNull(XyyProductSku::getSizeName)
                        .gt(XyyProductSku :: getStock, 0)
                        );
                if (CollectionUtils.isEmpty(skus)) {
                    continue;
                }
                // 库存计算
                int stock = 0;
                for (XyyProductSku sku : skus) {
                    stock += sku.getStock();
                }
                if(product.getUserPrice().compareTo(BigDecimal.ZERO) < 1){
                    log.info("--------------- 该商品: {} 售价异常, 不进行下放 ---------------",product.getGoodsId());
                    continue;
                }
                // 构建实体
                StoreProductCrmebRequest storeProductCrmebRequest = sourceXyyProductUtil.buildXyyProduct(product, skus);
                // 数据保存
                StoreProduct storeProduct = storeProductService.getByBarCode(storeProductCrmebRequest.getBarCode(), storeProductCrmebRequest.getSuppliersId(), storeProductCrmebRequest.getKeyword());
                boolean crmebUpdate = true;
                if (null != storeProduct && null != storeProduct.getLastPushTime()) {
                    long txyye = (System.currentTimeMillis() - storeProduct.getLastPushTime().getTime()) / 1000 / 60;
                    if (60 > txyye) {
                        log.info("--------------- 该商品: {} 上次喜洋洋更新时间: {} 小于一小时, 不进行更新 ---------------", storeProductCrmebRequest.getBarCode(), storeProduct.getLastPushTime());
                        crmebUpdate = false;
                        storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
                                .eq(StoreProduct::getId, storeProduct.getId())
                                .set(StoreProduct::getUpdateFlag, true)
                                );
                    }
                }
                if (crmebUpdate) {
                    storeProductService.saveOtProduct(storeProductCrmebRequest, storeProduct, stock);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}
